package controller;

import model.Aluno;
import java.sql.*;
import java.util.ArrayList;

/**
 * Classe que representa um Data Access Object para acessar/modificar a tabela ALUNO
 * do banco de dados do SADAF.
 * Esta classe segue o padrão SINGLETON.
 * @author Adriano
 * @see http://en.wikipedia.org/wiki/Singleton_pattern
 */
public class AlunoDAO {

    // Instância única do AlunoDAO.
    private static final AlunoDAO INSTANCE = new AlunoDAO();

    // Instância única da lista de Alunos
    private ArrayList<Aluno> listaDeAlunos;

    // Construtor privado para que outras classes não instanciem o AlunoDAO
    private AlunoDAO() {
        this.listaDeAlunos = this.montarListaDeAlunos();
    }

    /**
     * O acesso ao objeto AlunoDAO deve ser feito através do método getInstance.
     * Isto garante apenas uma instância de AlunoDAO.
     */
    public static AlunoDAO getInstance() {
        return INSTANCE;
    }

    /**
     * Retorna a lista de alunos
     * @return
     */
    public ArrayList<Aluno> getListaDeAlunos() {
        return this.listaDeAlunos;
    }

    /**
     * Cadastra um aluno no banco de dados do SADAF.
     * @param aluno Aluno a ser cadastrado.
     */
    public void cadastrar(Aluno aluno) {

        BancoDeDados bd = new BancoDeDados();
        try {
            bd.carregarDriver();
            bd.conectar(BancoDeDados.bdUrl, BancoDeDados.bdUsuario, BancoDeDados.bdSenha);
            bd.sql = "INSERT INTO ALUNO "
                    + "(MATRICULA, "
                    + "NOME) "
                    + "VALUES (?, ?);";
            bd.comandoSql = bd.connection.prepareStatement(bd.sql);
            bd.comandoSql.setString(1, aluno.getMatricula());
            bd.comandoSql.setString(2, aluno.getNome());
            bd.comandoSql.executeUpdate();
            bd.desconectar();

            listaDeAlunos.add(aluno);  //add o aluno na lista
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * Procura por um Aluno no banco de dados do SADAF cujo campo MATRICULA
     * na tabela ALUNO seja igual a matrícula passada por parâmetro.
     * @param matricula Matrícula utilizada como chave primária.
     * @return Objeto Aluno construído com os correspondentes campos da tabela ALUNO ou null caso não encontre nada.
     */
    public Aluno ProcurarAluno(String matricula) {

        Aluno retAluno                = null;
        int   tamanhoDaListaDeAlunos  = listaDeAlunos.size();

        for (int j = 0; j < tamanhoDaListaDeAlunos; j++) {
            if (listaDeAlunos.get(j).getMatricula().equals(matricula)) {
                retAluno = listaDeAlunos.get(j);
                break;
            }
        }

        return retAluno;
    }

    /**
     * Exclui um aluno do banco de dados do SADAF.
     * @param aluno Aluno que vai ser excluído.
     */
    public void excluir(Aluno aluno) {

        BancoDeDados bd = new BancoDeDados();
        try {
            bd.carregarDriver();
            bd.conectar(bd.bdUrl, bd.bdUsuario, bd.bdSenha);
            bd.sql = "DELETE FROM ALUNO WHERE MATRICULA = ?";
            bd.comandoSql = bd.connection.prepareStatement(bd.sql);
            bd.comandoSql.setString(1, aluno.getMatricula());
            bd.comandoSql.executeUpdate();
            bd.desconectar();

            int tamanhoDaListaDeAlunos = listaDeAlunos.size();
            for (int j = 0; j < tamanhoDaListaDeAlunos; j++) {
                if (listaDeAlunos.get(j).getMatricula().equals(aluno.getMatricula())) {
                    listaDeAlunos.remove(j);
                    break;
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * Acessa a tabela ALUNO no banco de dados e monta uma lista de Alunos.
     * Utilizado para montar/atualizar a variável listaDeAlunos.
     * @return ArrayList contendo os Alunos presentes no banco de dados.
     */
    private ArrayList<Aluno> montarListaDeAlunos() {

        ArrayList<Aluno> retArray = new ArrayList<Aluno>();
        BancoDeDados     bd       = new BancoDeDados();

        try {
            bd.carregarDriver();
            bd.conectar(bd.bdUrl, bd.bdUsuario, bd.bdSenha);
            bd.sql        = "SELECT * FROM ALUNO";
            bd.comandoSql = bd.connection.prepareStatement(bd.sql);
            ResultSet rs  = bd.comandoSql.executeQuery();

            while (rs.next()) {
                String matriculaAluno = rs.getString(1);
                String nomeAluno      = rs.getString(2);
                Aluno  aluno          = new Aluno(nomeAluno, matriculaAluno);
                retArray.add(aluno);
            }
            bd.desconectar();
        } catch (Exception e) {
            e.printStackTrace();
        }

        return retArray;
    }
}
